// Copyright 2022 jeff.li. and/or its affiliates.

#include <tbir/runtime/algorithm/trie_ref.h>

#include <tbir/runtime/algorithm/trie_private.h>
#include <tbir/runtime/container/list_ref.h>
#include <tbir/runtime/exceptions/exceptions.h>
#include <tbir/runtime/global_type_index.h>
#include <tbir/runtime/registry.h>
#include <tbir/runtime/runtime_value.h>

namespace tbir::runtime {

    template<>
    bool IsConvertible<Trie>(const Object *node) {
        return node ? node->IsInstance<Trie::ContainerType>() : Trie::_type_is_nullable;
    }

    Trie::Trie() {
        data_ = make_object<TrieNode>();
    }

    Trie::Trie(const std::map<string_view, int64_t> &dic) {
        data_ = make_object<TrieNode>(dic);
    }

    TrieNode *Trie::get() {
        MX_DPTR(Trie);
        return d;
    }

    void Trie::update(const string_view &w, int64_t val) const {
        MX_CHECK_DPTR(Trie);
        return d->Update(w, val);
    }

    void Trie::update(const unicode_view &w, int64_t val) const {
        MX_CHECK_DPTR(Trie);
        return d->Update(w, val);
    }

    void Trie::update(const Any &w, int64_t val) const {
        MX_CHECK_DPTR(Trie);
        return d->update(w, val);
    }

    int64_t Trie::PrefixSearch(const string_view &w, int64_t *val) const {
        MX_CHECK_DPTR(Trie);
        return d->PrefixSearch(w, val);
    }

    int64_t Trie::PrefixSearch(const unicode_view &w, int64_t *val) const {
        MX_CHECK_DPTR(Trie);
        return d->PrefixSearch(w, val);
    }

    Tuple Trie::prefix_search(const string_view &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search(w, pos);
    }

    Tuple Trie::prefix_search(const unicode_view &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search(w, pos);
    }

    Tuple Trie::prefix_search(const Any &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search(w, pos);
    }

    List Trie::prefix_search_all(const string_view &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search_all(w, pos);
    }

    List Trie::prefix_search_all(const unicode_view &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search_all(w, pos);
    }

    List Trie::prefix_search_all(const Any &w, int64_t pos) const {
        MX_CHECK_DPTR(Trie);
        return d->prefix_search_all(w, pos);
    }

    int Trie::save(const unicode_view &file_path) const {
        MX_CHECK_DPTR(Trie);
        return d->save(file_path);
    }

    int Trie::load(const unicode_view &file_path) const {
        MX_CHECK_DPTR(Trie);
        return d->load(file_path);
    }

    std::ostream &operator<<(std::ostream &os, Trie const &n) {
        os << "Trie(addr: " << n.get() << ")";
        return os;
    }

}  // namespace tbir::runtime
